Home:ALL Converter>Allow only one of specific value in Ruby array

Allow only one of specific value in Ruby array

Ask Time:2015-03-31T03:09:53         Author:Paul Groves

Json Formatter

What is the best way to allow only one of a specific value in an array?

For example, I would like to allow only one value of cat in the following array:

["dog", "cat", "cat", "hamster", "rabbit", "dog"]

such that it returned:

["dog", "cat", "hamster", "rabbit", "dog"]

EDIT: Apologies for not making this clear enough, I am not looking for uniq! I want to ensure that there is only 1 of a specified value.

Author:Paul Groves,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/29354285/allow-only-one-of-specific-value-in-ruby-array
Mark Thomas :

To make only one value unique:\n\na = [\"dog\", \"cat\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\n\n(a.count(\"cat\") - 1).times { a.delete_at(a.index(\"cat\"))}\n\n#=> [\"dog\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\n\n\nThis preserves the order of the elements in the array.\n\nTo delete consecutive items:\n\nUse Enumerable#chunk:\n\na = [\"dog\", \"cat\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\n\na.chunk(&:itself).map(&:first)\n\n#=> [\"dog\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\n\n\nNote that in Ruby < 2.2 you have to use chunk{|w| w} because itself isn't defined.",
2015-03-30T21:49:25
Cary Swoveland :

If you wish to modify the array in place:\n\ndef keep_one(arr, obj)\n i = arr.each_index.find { |i| arr[i] == obj }\n if i\n arr.delete(obj)\n arr.insert(i,obj)\n end\nend\n\narr = [\"dog\", \"cat\", \"cat\", 7.2, { a: 3}, \"cat\", \"dog\"]\n\na = arr.dup\nkeep_one(a,\"cat\")\na #=> [\"dog\", \"cat\", 7.2, {:a=>3}, \"dog\"] \n\na = arr.dup\nkeep_one(a,\"dog\")\na #=> [\"dog\", \"cat\", \"cat\", 7.2, {:a=>3}, \"cat\"] \n\na = arr.dup\nkeep_one(a,7.2)\na #=> [\"dog\", \"cat\", \"cat\", 7.2, {:a=>3}, \"cat\", \"dog\"] \n\na = arr.dup\nkeep_one(a,\"pig\")\na #=> [\"dog\", \"cat\", \"cat\", 7.2, {:a=>3}, \"cat\", \"dog\"] \n\n\nIf you do not wish to modify arr:\n\nkeep_one(arr.dup,\"cat\")\n #=> [\"dog\", \"cat\", 7.2, {:a=>3}, \"dog\"] \narr\n #=> [\"dog\", \"cat\", \"cat\", 7.2, {:a=>3}, \"dog\"] \n\n\nor\n\ndef keep_one(arr, obj)\n found = false\n arr.each_with_object([]) do |o,a|\n a << o unless o == obj && found\n found = true if o == obj\n end\nend\n",
2015-03-30T20:07:33
dwenzel :

If the order of elements does not matter:\n\nunique_element = \"cat\"\nanimals = [\"dog\", \"cat\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\nanimals << animals.delete(unique_element) if animals.include?(unique_element)\n\np animals\n#=> [\"dog\", \"hamster\", \"rabbit\", \"dog\", \"cat\"]\n\n\nOr, to keep it in the index of the first instance:\n\nunique_element = \"cat\"\nanimals = [\"dog\", \"cat\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\nif animals.include?(unique_element)\n index_position = animals.index(unique_element)\n animals.insert(index_position, animals.delete(unique_element))\nend\n\np animals\n#=> [\"dog\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\n",
2015-03-30T20:26:40
tadman :

You'll need a method that can remove duplicates:\n\nrequire 'set'\n\nlist = [\"dog\", \"cat\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\n\ndef limit(list, *entries)\n # Create a tracking table for terms that are limited\n entries = Hash[entries.to_a.flatten.collect { |i| [ i, 0 ] }]\n\n list.select do |i|\n case (entries[i])\n when 0\n entries[i] += 1\n i\n when nil\n i\n end\n end\nend\n\nputs limit(list, 'cat').inspect\n# => [\"dog\", \"cat\", \"hamster\", \"rabbit\", \"dog\"]\n\n\nYou could also roll this into a fancy subclass of Array that limits this for you, but there's a lot of hooks you'll have to add as elements can be added a variety of ways.",
2015-03-30T19:15:39
yy